import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { Reflector } from '@nestjs/core';
// 修正 UserLogService 的导入路径
import { UserLogService } from '../../modules/user-log/services/user-log.service';
// 修正 UserLog 实体的导入路径
import { UserActionType } from '../../modules/user-log/entities/user-log.entity';
import { API_NAME_KEY, ApiNameMetadata } from '../decorators/api-name.decorator';

@Injectable()
export class UserLogInterceptor implements NestInterceptor {
  private readonly logger = new Logger(UserLogInterceptor.name);

  constructor(
    private readonly userLogService: UserLogService,
    private readonly reflector: Reflector,
  ) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const startTime = Date.now();
    const request = context.switchToHttp().getRequest();
    const response = context.switchToHttp().getResponse();

    // 获取用户信息
    const user = request.user;
    const userId = user?.id;
    const username = user?.username || 'anonymous';

    // 获取请求信息
    const ipAddress = this.getClientIP(request);
    const userAgent = request.headers['user-agent'];
    const requestUrl = request.url;
    const requestMethod = request.method;
    const requestParams = {
      query: request.query,
      body: request.body,
      params: request.params,
    };

    return next.handle().pipe(
      tap(async (data) => {
        try {
          const executionTime = Math.max(0, Date.now() - startTime);
          
          // 记录用户行为日志
          await this.logUserAction(
            context,
            userId,
            username,
            request,
            response,
            requestUrl,
            requestMethod,
            requestParams,
            data,
            executionTime,
            ipAddress,
            userAgent,
          );
        } catch (logError) {
          this.logger.error('记录用户行为日志失败', logError.stack);
          // 不抛出错误，避免影响正常响应
        }
      }),
      catchError(async (error) => {
        try {
          const executionTime = Math.max(0, Date.now() - startTime);
          
          // 记录错误日志
          await this.logUserAction(
            context,
            userId,
            username,
            request,
            response,
            requestUrl,
            requestMethod,
            requestParams,
            null, // 正常响应数据为空
            executionTime,
            ipAddress,
            userAgent,
            error, // 传递错误对象
          );
        } catch (logError) {
          this.logger.error('记录错误日志失败', logError.stack);
        }
        
        throw error;
      }),
    );
  }

  private async logUserAction(
    context: ExecutionContext,
    userId: string,
    username: string,
    request: any,
    response: any,
    requestUrl: string,
    requestMethod: string,
    requestParams: any,
    responseData: any,
    executionTime: number,
    ipAddress: string,
    userAgent: string,
    error?: any,
  ) {
    try {
      // 如果没有用户ID，不记录日志
      if (!userId) {
        return;
      }

      // 安全地序列化响应数据
      let safeResponseData;
      try {
        if (error) {
          // 如果是错误，只记录错误的基本信息
          safeResponseData = {
            error: error.message || '未知错误',
            stack: error.stack ? error.stack.split('\n').slice(0, 3).join('\n') : undefined,
            name: error.name || 'Error'
          };
        } else {
          // 如果是正常响应，尝试序列化
          safeResponseData = JSON.parse(JSON.stringify(responseData || {}));
        }
      } catch (serializeError) {
        // 如果序列化失败，使用安全的默认值
        safeResponseData = {
          error: '响应数据序列化失败',
          originalError: error ? error.message : '未知错误'
        };
      }

      // 安全地序列化请求参数
      let safeRequestParams;
      try {
        safeRequestParams = JSON.parse(JSON.stringify(requestParams || {}));
      } catch (serializeError) {
        safeRequestParams = { error: '请求参数序列化失败' };
      }

      // 根据请求路径和方法确定操作类型和描述
      const { actionType, actionDescription, resourceType, resourceId } = 
        this.determineActionType(requestUrl, requestMethod, requestParams);

      // 提取接口名称 - 优先从装饰器获取，否则使用默认逻辑
      const apiName = this.extractApiNameWithDecorator(context, requestUrl, requestMethod);

      // 记录日志
      await this.userLogService.logUserAction({
        userId,
        username,
        actionType,
        actionDescription,
        resourceType,
        resourceId,
        requestUrl,
        requestMethod,
        apiName,
        requestParams: safeRequestParams,
        responseData: safeResponseData,
        executionTime,
        ipAddress,
        userAgent,
      });
    } catch (logError) {
      this.logger.error('记录用户行为日志失败', logError.stack);
      // 不重新抛出错误，避免影响正常流程
    }
  }

  private determineActionType(
    requestUrl: string,
    requestMethod: string,
    requestParams: any,
  ): { 
    actionType: UserActionType; 
    actionDescription: string; 
    resourceType?: string; 
    resourceId?: string 
  } {
    // 登录相关
    if (requestUrl.includes('/auth/login') && requestMethod === 'POST') {
      return {
        actionType: UserActionType.LOGIN,
        actionDescription: '用户登录',
      };
    }

    // 登出相关
    if (requestUrl.includes('/auth/logout') && requestMethod === 'POST') {
      return {
        actionType: UserActionType.LOGOUT,
        actionDescription: '用户登出',
      };
    }

    // 用户管理相关
    if (requestUrl.includes('/users')) {
      switch (requestMethod) {
        case 'POST':
          if (requestUrl.includes('/create')) {
            return {
              actionType: UserActionType.CREATE,
              actionDescription: '创建用户',
              resourceType: 'user',
              resourceId: requestParams.body?.id,
            };
          }
          if (requestUrl.includes('/update')) {
            return {
              actionType: UserActionType.UPDATE,
              actionDescription: '更新用户',
              resourceType: 'user',
              resourceId: requestParams.body?.id,
            };
          }
          if (requestUrl.includes('/delete')) {
            if (requestUrl.includes('/batch-delete')) {
              return {
                actionType: UserActionType.BATCH_DELETE,
                actionDescription: '批量删除用户',
                resourceType: 'user',
              };
            }
            return {
              actionType: UserActionType.DELETE,
              actionDescription: '删除用户',
              resourceType: 'user',
              resourceId: requestParams.body?.id,
            };
          }
          break;
        case 'GET':
          if (requestUrl.includes('/list')) {
            return {
              actionType: UserActionType.QUERY,
              actionDescription: '查询用户列表',
              resourceType: 'user',
            };
          }
          if (requestUrl.includes('/profile')) {
            return {
              actionType: UserActionType.QUERY,
              actionDescription: '查询用户信息',
              resourceType: 'user',
            };
          }
          break;
      }
    }

    // 默认情况
    return {
      actionType: UserActionType.OTHER,
      actionDescription: `${requestMethod} ${requestUrl}`,
    };
  }

  private getClientIP(request: any): string {
    return (
      request.headers['x-forwarded-for'] ||
      request.headers['x-real-ip'] ||
      request.socket?.remoteAddress ||
      (request.socket?.socket?.remoteAddress 
        ? request.socket.socket.remoteAddress 
        : 'unknown')
    );
  }

  /**
   * 提取接口名称 - 优先从装饰器获取，否则使用默认逻辑
   * @param context 执行上下文
   * @param requestUrl 请求URL
   * @param requestMethod 请求方法
   * @returns 接口名称
   */
  private extractApiNameWithDecorator(
    context: ExecutionContext,
    requestUrl: string,
    requestMethod: string,
  ): string {
    // 尝试从装饰器获取API名称
    const apiNameMetadata = this.reflector.get<ApiNameMetadata>(
      API_NAME_KEY,
      context.getHandler(),
    );

    if (apiNameMetadata?.name) {
      return apiNameMetadata.name;
    }

    // 如果没有装饰器，使用默认逻辑
    return this.extractApiName(requestUrl, requestMethod);
  }

  /**
   * 提取接口名称（默认逻辑）
   * @param requestUrl 请求URL
   * @param requestMethod 请求方法
   * @returns 接口名称
   */
  private extractApiName(requestUrl: string, requestMethod: string): string {
    // 移除查询参数
    const urlWithoutQuery = requestUrl.split('?')[0];
    
    // 根据URL路径和方法生成接口名
    const pathParts = urlWithoutQuery.split('/').filter(part => part);
    
    if (pathParts.length === 0) {
      return `${requestMethod} /`;
    }
    
    // 处理常见的API路径模式
    if (pathParts[0] === 'auth') {
      if (pathParts[1] === 'login') return '用户登录';
      if (pathParts[1] === 'logout') return '用户登出';
      return '认证相关';
    }
    
    if (pathParts[0] === 'users') {
      if (pathParts[1] === 'create') return '创建用户';
      if (pathParts[1] === 'update') return '更新用户';
      if (pathParts[1] === 'delete') return '删除用户';
      if (pathParts[1] === 'batch-delete') return '批量删除用户';
      if (pathParts[1] === 'list') return '获取用户列表';
      if (pathParts[1] === 'profile') return '获取用户信息';
      return '用户管理';
    }
    
    if (pathParts[0] === 'file') {
      if (pathParts[1] === 'upload') return '文件上传';
      if (pathParts[1] === 'download') return '文件下载';
      if (pathParts[1] === 'delete') return '删除文件';
      if (pathParts.length === 1) return '获取文件列表';
      return '文件管理';
    }
    
    if (pathParts[0] === 'user-logs') {
      if (pathParts[1] === 'list') return '获取日志列表';
      if (pathParts[1] === 'by-user') return '按用户查询日志';
      if (pathParts[1] === 'by-action') return '按操作类型查询日志';
      return '日志管理';
    }
    
    if (pathParts[0] === 'security-log') {
      if (pathParts.length === 1) return '获取安全日志列表';
      if (pathParts[1] === 'statistics') return '获取安全统计信息';
      if (pathParts[1] === 'create') return '创建安全日志';
      if (pathParts[1] === 'update') return '更新安全日志';
      if (pathParts[1] === 'delete') return '删除安全日志';
      if (pathParts[1] === 'batch-mark-handled') return '批量标记为已处理';
      if (pathParts[1] === 'clean-old-logs') return '清理旧的安全日志';
      if (pathParts[1] && pathParts[1] !== 'create' && pathParts[1] !== 'update' && pathParts[1] !== 'delete') return '获取安全日志详情';
      return '安全日志管理';
    }
    
    // 默认情况：使用路径和方法组合
    return `${requestMethod} ${pathParts.join('/')}`;
  }
} 